<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="utf-8">
    <title>扫一扫</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <link rel="shortcut icon" type="image/x-icon" href="../favicon.ico"/>
    <link rel="stylesheet" href="../layui-admin/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../layui-admin/style/admin.css" media="all">
</head>
<body>
<div id="scan-layer" class="layui-card" style="display: none;">
    <div class="layui-card-header layui-icon layui-icon-app">
        扫一扫
    </div>
    <div class="layui-card-body layui-form">
        <div class="layui-form-item">
            <label for="scan-result"></label><input id="scan-result" class="layui-input" placeholder="扫一扫"/>
        </div>
        <div class="layui-form-item">
            <label for="video-select"></label><select id="video-select"></select>
        </div>
        <div class="layui-form-item">
            <button id="scan-code" class="layui-btn layui-btn-fluid">扫一扫</button>
        </div>
    </div>
</div>
<div id="scan-video"
     style="display:none;background:black;width:100%;height:100%;overflow:hidden;margin:0;position:absolute;z-index:99999999">
    <video id="video" style="display:none;width:100%;height:100%;position:relative;"></video>
    <canvas id="canvas" style="width:100%;height:100%;position:relative;"></canvas>
    <i id="scan-close" class="layui-icon layui-icon-left"
       style="display:block;position:absolute;top:10px;left:10px;font-size:30px;color:white;"></i>
    <i id="scan-image" class="layui-icon layui-icon-picture"
       style="display:block;position:absolute;bottom:10px;left:10px;font-size:30px;color:white;"></i>
    <input id="scan-file" type="file" accept=".jpg,.png" style="display: none;"/>
    <audio id="scan-audio" src="raw/scan-code.wav" preload="auto" style="display: none;"></audio>
</div>
<script src="../layui-admin/layui/layui.js"></script>
<script src="js/jsQR.js"></script>
<script>
    layui.config({
        base: '../layui-admin/'
    }).extend({
        index: 'lib/index'
    }).use(['index'], function () {
        const $ = layui.$;
        const form = layui.form;
        const layer = layui.layer;
        layer.open({
            type: 1
            , title: false
            , resize: false
            , closeBtn: false
            , area: '300px'
            , content: $('#scan-layer')
        });
        try {
            navigator.mediaDevices.enumerateDevices().then(function (devices) {
                console.log(devices);
                const videos = [];
                devices.forEach(function (device) {
                    const kind = device.kind === 'video' ? 'videoinput' : device.kind;
                    if (kind === 'videoinput') {
                        const label = device.label || `Video device ${videos.length + 1}`;
                        const deviceId = device.deviceId || device.id;
                        videos.push({label, deviceId});
                        $('#video-select').append(new Option(label, deviceId));
                    }
                });
                form.render("select");
            }).catch(function (err) {
                layer.msg(err);
            });
        } catch (err) {
            layer.msg(err);
        }
        let anim;
        const video = document.getElementById('video');
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext("2d");
        $('#scan-code').on('click', function () {
            $('#scan-result').val('');
            $('#scan-video').show();
            const deviceId = $('#video-select').val();
            try {
                navigator.mediaDevices.getUserMedia({
                    video: (deviceId) ? {deviceId: {exact: deviceId}} : {facingMode: 'environment'}
                }).then(function (stream) {
                    video.srcObject = stream;
                    video.play();
                    anim = requestAnimationFrame(tick);
                }).catch(function (err) {
                    layer.msg(err);
                });
            } catch (err) {
                layer.msg(err);
            }
        });
        $('#scan-image').on('click', function () {
            $("#scan-file").click();
        });
        $("#scan-file").on("change", function () {
            const that = this;
            const files = this.files || [];
            if (files.length === 0) return;
            const fileReader = new FileReader();
            fileReader.readAsDataURL(files[0]);
            fileReader.onload = function () {
                const image = new Image();
                image.src = fileReader.result;
                image.onload = function () {
                    stop(scan(this, this.width, this.height));
                };
                that.value = null;
            };
        });
        $('#scan-close').on('click', function () {
            stop();
        });

        function scan(image, width, height) {
            canvas.width = width;
            canvas.height = height;
            ctx.drawImage(image, 0, 0, width, height);
            const img = ctx.getImageData(0, 0, width, height);
            console.log(img);
            return jsQR(img.data, img.width, img.height);
        }

        function tick() {
            if (video.readyState === video.HAVE_ENOUGH_DATA) {
                const qr = scan(video, video.videoWidth, video.videoHeight);
                if (qr && qr.data) {
                    stop(qr);
                    return;
                }
            }
            anim = requestAnimationFrame(tick);
        }

        function stop(qr) {
            console.log(qr);
            if (qr && qr.data) {
                $('#scan-result').val(qr.data);
            }
            cancelAnimationFrame(anim);
            $('#scan-video').hide();
            video.pause();
        }
    });
</script>
</body>
</html>
